package cn.ecnu.controller;

import cn.ecnu.constant.ResponseStatus;
import cn.ecnu.dao.OrderDao;
import cn.ecnu.dao.RecordDao;
import cn.ecnu.entity.Car;
import cn.ecnu.entity.Employee;
import cn.ecnu.entity.Order;
import cn.ecnu.entity.Record;
import cn.ecnu.feign.ManagementFeignService;
import cn.ecnu.utils.Converter;
import cn.ecnu.utils.RouteGenerator;
import cn.ecnu.vo.OrderVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import cn.ecnu.utils.R;

import javax.annotation.Resource;
import java.util.*;

@RefreshScope
@RestController
@RequestMapping("/order")
public class OrderController {

    @Resource
    private OrderDao orderDao;

    @Resource
    private RecordDao recordDao;

    @Resource
    private Converter converter;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private RouteGenerator routeGenerator;

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private ManagementFeignService managementFeignService;

    @GetMapping("/getOrderByOid/{id}")
    public R getOrderByOid(@PathVariable("id") String id) {
        try {
            Order order = orderDao.getOrderByOid(id);
            OrderVo orderVo = converter.OrderToVo(order);
            return R.ok().put("data", orderVo);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    @GetMapping("/user/getMyOnWayReceiveOrdersByPhone/{phone}")
    public R getMyOnWayReceiveOrdersByPhone(@PathVariable("phone") String phone) {
        try {
            Order[] orders = orderDao.getMyOnWayReceiveOrdersByPhone(phone);
            return R.ok().put("data", orders);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    @GetMapping("/user/getMyOverReceiveOrdersByPhone/{phone}")
    public R getMyOverReceiveOrdersByPhone(@PathVariable("phone") String phone) {
        try {
            Order[] orders = orderDao.getMyOverReceiveOrdersByPhone(phone);
            return R.ok().put("data", orders);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }

    }

    @GetMapping("/user/getMyOnWaySendOrdersByUid/{id}")
    public R getMyOnWaySendOrdersByUid(@PathVariable("id") String id) {
        try {
            Order[] orders = orderDao.getMyOnWaySendOrdersByUid(id);
            return R.ok().put("data", orders);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }

    }

    @GetMapping("/user/getMyOverSendOrdersByUid/{id}")
    public R getMyOverSendOrdersByUid(@PathVariable("id") String id) {
        try {
            Order[] orders = orderDao.getMyOverSendOrdersByUid(id);
            return R.ok().put("data", orders);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }

    }

    @GetMapping("/user/getMyCanceledSendOrdersByUid/{id}")
    public R getMyCanceledSendOrdersByUid(@PathVariable("id") String id) {
        try {
            Order[] orders = orderDao.getMyCanceledSendOrdersByUid(id);
            return R.ok().put("data", orders);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }

    }

    @PostMapping("/user/submitOrder")
    public R submitOrder(@RequestBody Order order) {
        try {
            String uuid = ResponseStatus.uuidGenerator();
            order.setId(uuid);
            order.setOrderTime(new Date());
            order.setStatus("订单创建");
            order.setRoute(routeGenerator.generate(order.getSendAddressId(), order.getReceiveAddressId()));
            order.setCurrentIndex(0);
            orderDao.submitOrder(order);
            //创建一条记录
            Record record = new Record();
            record.setDetail("订单创建成功");
            record.setTime(new Date());
            record.setOid(uuid);
            recordDao.addRecord(record);
            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    //只能取消 订单创建 状态下的订单
    @GetMapping("/user/cancelOrder/{id}")
    public R cancelOrder(@PathVariable("id") String id) {
        try {
            Order order = orderDao.getOrderByOid(id);
            if (!order.getStatus().equals("订单创建")) {
                return R.ok().put("msg", "订单已在进行中，取消失败，请联系客服");
            } else {
                order.setStatus("已取消");
                order.setCancelTime(new Date());
                orderDao.updateOrder(order);
                //创建一条记录
                Record record = new Record();
                record.setDetail("订单取消");
                record.setTime(new Date());
                record.setOid(id);
                recordDao.addRecord(record);
                return R.ok().put("msg", "取消成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    /*
    分配订单给快递员
        1.快递员获得任务，courier_eid_mission这个set中增加订单id
        2.修改订单状态
        3.订单的eid修改为快递员的id
        4.订单新增record
    */
    @GetMapping("/allocateCourier/{oid}/{eid}")
    public R allocateCourier(@PathVariable("oid") String oid, @PathVariable("eid") String eid) {
        try {
            //1.快递员获得任务，courier_eid_mission这个set中增加订单id
            String key = new StringBuilder().append("courier_").append(eid).append("_mission").toString();
            redisTemplate.opsForSet().add(key, oid);
            //2.修改订单状态
            //3.订单的eid修改为快递员的id
            Order order = orderDao.getOrderByOid(oid);
            String oriStatus = order.getStatus();
            if (oriStatus.equals("订单创建")) {
                order.setStatus("待取件");
            } else {
                order.setStatus("待派送");
            }
            order.setEid(eid);
            orderDao.updateOrder(order);
            //4.订单新增record
            Record record = new Record();
            record.setOid(oid);
            record.setTime(new Date());
            Employee employee = objectMapper.convertValue(managementFeignService.getEmployeeById(eid).get("data"), Employee.class);
            String name = employee.getName();
            String phone = employee.getPhone();
            String detail;
            if (oriStatus.equals("订单创建")) {
                detail = new StringBuilder().append("快递员").append(name)
                        .append("正在取件的路上，联系电话：").append(phone).toString();
            } else {
                detail = new StringBuilder().append("快递员").append(name)
                        .append("负责派送您的包裹，联系电话").append(phone).toString();
            }
            record.setDetail(detail);
            recordDao.addRecord(record);
            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    //simulate
    /*
    快递员取件
        1.修改订单状态
        2.订单新增record
    */
    @GetMapping("/courierGetPackage/{oid}/{eid}")
    public R courierGetPackage(@PathVariable("oid") String oid, @PathVariable("eid") String eid) {
        try {
            //1.修改订单状态
            Order order = orderDao.getOrderByOid(oid);
            String oriStatus = order.getStatus();
            if (oriStatus.equals("待派送")) {
                order.setStatus("派送中");
            } else {
                order.setStatus("投递中");
            }
            orderDao.updateOrder(order);
            //2.订单新增record
            Record record = new Record();
            record.setOid(oid);
            record.setTime(new Date());
            Employee employee = objectMapper.convertValue(managementFeignService.getEmployeeById(eid).get("data"), Employee.class);
            String name = employee.getName();
            String phone = employee.getPhone();
            String detail;
            if (oriStatus.equals("待取件")) {
                //快递员xxx正携带包裹前往中转站，联系电话：xxx
                detail = new StringBuilder().append("快递员").append(name)
                        .append("正携带包裹前往中转站，联系电话：").append(phone).toString();
            } else {
                //快递员xxx正在为您派送，联系电话：xxx
                detail = new StringBuilder().append("快递员").append(name)
                        .append("正在为您派送，联系电话").append(phone).toString();
            }
            record.setDetail(detail);
            recordDao.addRecord(record);
            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    //simulate
    /*
    快递员将包裹送达中转站：
        1.订单状态修改为“待揽件”
        2.订单新增record，“您的包裹到达中转站，等待揽件中”
        3.快递员完成任务，courier_eid_mission这个set中删除对应订单id
        4.订单的eid修改为null
        5.快递员的服务总单量+1
    */
    @GetMapping("/courierArriveStation/{oid}/{eid}")
    public R courierArriveStation(@PathVariable("oid") String oid, @PathVariable("eid") String eid) {
        try {
            //3.快递员完成任务，courier_eid_mission这个set中删除对应订单id
            String key = new StringBuilder().append("courier_").append(eid).append("_mission").toString();
            redisTemplate.opsForSet().remove(key, oid);
            //1.订单状态修改为“待揽件”
            //4.订单的eid修改为null
            Order order = orderDao.getOrderByOid(oid);
            order.setStatus("待揽件");
            order.setEid(null);
            orderDao.updateOrder(order);
            //4.订单新增record，“您的包裹到达中转站，等待揽件中”
            Record record = new Record();
            record.setOid(oid);
            record.setTime(new Date());
            String detail = "您的包裹到达中转站，等待揽件中";
            record.setDetail(detail);
            recordDao.addRecord(record);
            //5.快递员的服务总单量+1
            Employee employee = objectMapper.convertValue(managementFeignService.getEmployeeById(eid).get("data"), Employee.class);
            employee.setTotalWorkingAmount(employee.getTotalWorkingAmount() + 1);
            managementFeignService.updateEmployee(employee);
            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    //simulate
    /*
    揽件员揽件：
        1.订单状态修改为“已揽件”
        2.订单新增record，“您的包裹已被中转站揽件”
        3.揽件员的服务总单量+1
    */
    @GetMapping("/collectPackage/{oid}/{eid}")
    public R collectPackage(@PathVariable("oid") String oid, @PathVariable("eid") String eid) {
        try {
            //1.订单状态修改为“待揽件”
            Order order = orderDao.getOrderByOid(oid);
            order.setStatus("已揽件");
            orderDao.updateOrder(order);
            //2.订单新增record，“您的包裹到达中转站，等待揽件中”
            Record record = new Record();
            record.setOid(oid);
            record.setTime(new Date());
            String detail = "您的包裹已被中转站揽件";
            record.setDetail(detail);
            recordDao.addRecord(record);
            //3.揽件员的服务总单量+1
            Employee employee = objectMapper.convertValue(managementFeignService.getEmployeeById(eid).get("data"), Employee.class);
            employee.setTotalWorkingAmount(employee.getTotalWorkingAmount() + 1);
            managementFeignService.updateEmployee(employee);
            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    /*
    分配运输员：
        1.运输员获得任务，transmission_eid_mission这个set中增加订单id
        2.订单状态转换为"待运输"状态
        3.订单的eid修改为运输员的id
        4.订单新增record，"运输员xxx负责运输您的包裹，从xxx到xxx，联系电话：xxx"
        5.如果是运输员的第一个订单，eid_dst设置为当前的目的地
    分配车辆：
        1.订单的cid修改为车辆的id
        2.车辆进入busy状态
        3.如果是运输员的第一个订单，eid_car设置为cid
    */
    @GetMapping("/allocateDriverAndCar/{oid}/{eid}/{cid}")
    public R allocateDriverAndCar(@PathVariable("oid") String oid, @PathVariable("eid") String eid,
                                  @PathVariable("cid") String cid) {
        try {
            Order order = orderDao.getOrderByOid(oid);
            //1.运输员获得任务，transmission_eid_mission这个set中增加订单id
            String key = new StringBuilder().append("transmission_").append(eid).append("_mission").toString();
            redisTemplate.opsForSet().add(key, oid);
            //5.如果是运输员的第一个订单，eid_dst设置为当前的目的地
            //  3.如果是运输员的第一个订单，eid_car设置为cid
            if (redisTemplate.opsForSet().size(key) == 1) {
                //得到订单的目的地
                String destination = order.getRoute().split("\\|")[order.getCurrentIndex() + 1];
                redisTemplate.opsForValue().set(eid + "_dst", destination);
                redisTemplate.opsForValue().set(eid + "_car", cid);
            }
            //2.订单状态转换为"待运输"状态
            //3.订单的eid修改为运输员的id
            //  1.订单的cid修改为车辆的id
            order.setStatus("待运输");
            order.setEid(eid);
            order.setCid(cid);
            orderDao.updateOrder(order);
            //4.订单新增record，"运输员xxx负责运输您的包裹，从xxx到xxx，联系电话：xxx"
            Record record = new Record();
            record.setOid(oid);
            record.setTime(new Date());
            Employee employee = objectMapper.convertValue(managementFeignService.getEmployeeById(eid).get("data"), Employee.class);
            String name = employee.getName();
            String phone = employee.getPhone();
            String[] cities = order.getRoute().split("\\|");
            String currentCity = cities[order.getCurrentIndex()];
            String targetCity = cities[order.getCurrentIndex() + 1];
            String detail = new StringBuilder().append("运输员").append(name)
                    .append("负责运输您的包裹，从").append(currentCity).append("到").append(targetCity)
                    .append("，联系电话：").append(phone).toString();
            record.setDetail(detail);
            recordDao.addRecord(record);
            //  2.车辆进入busy状态
            Car car = objectMapper.convertValue(managementFeignService.getCarById(cid).get("data"), Car.class);
            car.setFree(0);
            managementFeignService.updateCar(car);
            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    //simulate
    /*
    司机确认拿货，对于每一个订单：
        1.订单状态修改为“运输中”
        2.订单新增record，“您的包裹正由运输员xxx运输中，联系电话：xxx”
    对于司机：
        1.司机进入busy状态
    */
    @GetMapping("/driverGetPackage/{eid}")
    public R driverGetPackage(@PathVariable("eid") String eid) {
        try {
            String key = new StringBuilder().append("transmission_").append(eid).append("_mission").toString();
            HashSet<String> orderIds = (HashSet<String>) redisTemplate.opsForSet().members(key);

            //得到运输员的name和phone
            Employee employee = objectMapper.convertValue(managementFeignService.getEmployeeById(eid).get("data"), Employee.class);
            String name = employee.getName();
            String phone = employee.getPhone();
            //对于司机：
            //    1.司机进入busy状态
            redisTemplate.opsForSet().add("busy_transmission_list", eid);

            //所在地与目的地
            String currentCity = null;
            String targetCity = null;

            //对于每一个订单：
            for (String oid : orderIds) {
                //1.订单状态修改为“运输中”
                Order order = orderDao.getOrderByOid(oid);
                order.setStatus("运输中");
                orderDao.updateOrder(order);
                //2.订单新增record，“您的包裹正由运输员xxx运输中，从xxx到xxx，联系电话：xxx”
                Record record = new Record();
                record.setOid(oid);
                record.setTime(new Date());
                if (currentCity == null) {
                    String[] cities = order.getRoute().split("\\|");
                    currentCity = cities[order.getCurrentIndex()];
                    targetCity = cities[order.getCurrentIndex() + 1];
                }
                String detail = new StringBuilder().append("您的包裹正由运输员").append(name)
                        .append("运输中，从").append(currentCity).append("到").append(targetCity)
                        .append("，联系电话：").append(phone).toString();
                record.setDetail(detail);
                recordDao.addRecord(record);
            }
            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    //simulate
    /*
    车辆到达中转站，此时对于车上的每一个订单：
        1.订单状态修改为“待揽件”
        2.订单新增record，“您的包裹到达中转站，等待揽件中”
        3.transmission_eid_mission这个set中删除对应订单id
        4.订单的eid、cid修改为null
        5.订单的currentIndex更新
    对于运输员：
        1.服务总单量+1
        2.location更新为当前位置
        3.进入空闲状态
        4.eid_car和eid_dst移除
    对于车辆：
        1.车辆设置为空闲状态
        2.location更新为当前位置
    */
    @GetMapping("/driverArriveStation/{eid}")
    public R driverArriveStation(@PathVariable("eid") String eid) {
        try {
            String key = new StringBuilder().append("transmission_").append(eid).append("_mission").toString();
            HashSet<String> orderIds = (HashSet<String>) redisTemplate.opsForSet().members(key);
            String currentCity = null;
            String cid = null;
            //对于车上的每一个订单：
            for (String oid : orderIds) {
                //1.订单状态修改为“待揽件”
                //4.订单的eid、cid修改为null
                //5.订单的currentIndex更新
                Order order = orderDao.getOrderByOid(oid);
                if (currentCity == null) {
                    currentCity = order.getRoute().split("\\|")[order.getCurrentIndex()];
                    cid = order.getCid();
                }
                order.setStatus("待揽件");
                order.setEid(null);
                order.setCid(null);
                order.setCurrentIndex(order.getCurrentIndex() + 1);
                orderDao.updateOrder(order);
                //2.订单新增record，“您的包裹到达中转站，等待揽件中”
                Record record = new Record();
                record.setOid(oid);
                record.setTime(new Date());
                String detail = "您的包裹到达中转站，等待揽件中";
                record.setDetail(detail);
                recordDao.addRecord(record);
                //3.transmission_eid_mission这个set中删除对应订单id
                redisTemplate.opsForSet().remove(key, oid);
            }

            //对于运输员：
            //   1.服务总单量+1
            //   2.location更新为当前位置
            Employee employee = objectMapper.convertValue(managementFeignService.getEmployeeById(eid).get("data"), Employee.class);
            employee.setTotalWorkingAmount(employee.getTotalWorkingAmount() + 1);
            employee.setLocation(currentCity);
            managementFeignService.updateEmployee(employee);
            //  3.进入空闲状态
            redisTemplate.opsForSet().remove("busy_transmission_list", eid);
            //  4.eid_car和eid_dst移除
            redisTemplate.delete(eid + "_car");
            redisTemplate.delete(eid + "_dst");

            //对于车辆：
            //    1.车辆设置为空闲状态
            //    2.location更新为当前位置
            Car car = objectMapper.convertValue(managementFeignService.getCarById(cid).get("data"), Car.class);
            car.setFree(1);
            car.setLocation(currentCity);
            managementFeignService.updateCar(car);

            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    //simulate
    /*
    用户签收：
    1.订单状态修改为“已签收”，并设置完成时间
    2.订单新增record，“您的包裹已签收”
    3.快递员完成任务，courier_eid_mission这个set中删除对应订单id
    4.订单的eid修改为null
    5.快递员的服务总单量+1
    */
    @GetMapping("/courierArriveHome/{oid}/{eid}")
    public R courierArriveHome(@PathVariable("eid") String eid, @PathVariable("oid") String oid) {
        try {
            //1.订单状态修改为“已签收”，并设置完成时间
            //4.订单的eid修改为null
            Order order = orderDao.getOrderByOid(oid);
            order.setStatus("已签收");
            order.setFinishTime(new Date());
            order.setEid(null);
            orderDao.updateOrder(order);
            //2.订单新增record，“您的包裹已签收”
            Record record = new Record();
            record.setOid(oid);
            record.setTime(new Date());
            String detail = "您的包裹已签收";
            record.setDetail(detail);
            recordDao.addRecord(record);
            //3.快递员完成任务，courier_eid_mission这个set中删除对应订单id
            String key = new StringBuilder().append("courier_").append(eid).append("_mission").toString();
            redisTemplate.opsForSet().remove(key, oid);
            //5.快递员的服务总单量+1
            Employee employee = objectMapper.convertValue(managementFeignService.getEmployeeById(eid).get("data"), Employee.class);
            employee.setTotalWorkingAmount(employee.getTotalWorkingAmount() + 1);
            managementFeignService.updateEmployee(employee);

            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    @GetMapping("/getOnWayOrders")
    public R getOnWayOrders() {
        try {
            Order[] orders = orderDao.getOnWayOrders();
            return R.ok().put("data", orders);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    @GetMapping("/getOverOrders")
    public R getOverOrders() {
        try {
            ArrayList<Order> orders = orderDao.getOrdersByStatus("已签收");
            return R.ok().put("data", orders);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    @GetMapping("/getCanceledOrders")
    public R getCanceledOrders() {
        try {
            ArrayList<Order> orders = orderDao.getOrdersByStatus("已取消");
            return R.ok().put("data", orders);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    @GetMapping("/getOrdersWaitingCourier")
    public R getOrdersWaitingCourier() {
        try {
            ArrayList<Order> orders = orderDao.getOrdersByStatus("订单创建");
            ArrayList<Order> collectedOrders = orderDao.getOrdersByStatus("已揽件");
            for (Order order : collectedOrders) {
                String[] cities = order.getRoute().split("\\|");
                if (order.getCurrentIndex() == cities.length - 1) {
                    orders.add(order);
                }
            }
            return R.ok().put("data", orders);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    @GetMapping("/getOrdersWaitingDriver")
    public R getOrdersWaitingDriver() {
        try {
            ArrayList<Order> orders = new ArrayList<>();
            ArrayList<Order> collectedOrders = orderDao.getOrdersByStatus("已揽件");
            for (Order order : collectedOrders) {
                String[] cities = order.getRoute().split("\\|");
                if (order.getCurrentIndex() < cities.length - 1) {
                    orders.add(order);
                }
            }
            return R.ok().put("data", orders);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }

    @GetMapping("/getPotentialCar/{eid}")
    public R getPotentialCar(@PathVariable("eid") String eid) {
        try {
            String key = eid + "_car";
            if (redisTemplate.hasKey(key)) {
                String carId = (String) redisTemplate.opsForValue().get(key);
                return R.ok().put("data", carId);
            } else {
                return R.ok().put("data", null);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("未知错误");
        }
    }


}














